home *** CD-ROM | disk | FTP | other *** search
- /*
- * A simple DB meter program (experimental)
- *
- * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- */
-
- /* This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/time.h>
-
- #define BUF_SIZE 10000
- #define QUEUE_SIZE 1000
-
- int queue[QUEUE_SIZE], front = 0, end = 0, write_lock;
-
- void print_bar(int);
- void write_finished(int);
-
- int main(int argc, char *argv[])
- {
- char buf[BUF_SIZE];
- int i, j, fd = 0, bytes_read, remain = 0, interval_size, first_enter = 1, temp;
- struct itimerval value, ovalue = {0, 0, 0, 0};
-
- if (argc < 3 || argc > 4) {
- fprintf(stderr, "\nUsage: dbmeter <infile> <samplerate> [outfile]\n");
- exit(-1);
- }
-
- /* Update meter every 1/10th second (every samplerate/10 samples) */
- interval_size = atoi(argv[2]) / 10;
-
- if (strcmp("-", argv[1]))
- if ((fd = open(argv[1], O_RDONLY, 0)) == -1) {
- perror(argv[1]);
- exit(-1);
- }
-
- if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
- perror(argv[1]);
- exit(-1);
- }
- if (argc == 4 && !strcmp(argv[3], "-"))
- write(1, buf, bytes_read);
-
- while (bytes_read) {
- if (remain) {
- for (i = 0; i < remain; i++)
- temp += abs((unsigned char) buf[i]-0x80);
- /* Wait until queue not full */
- while ((end == QUEUE_SIZE && front == 0) || end == front-1);
- queue[end++] = temp / interval_size;
- end %= QUEUE_SIZE;
- }
- for (i = remain; i < bytes_read; i += interval_size) {
- temp = 0;
- for (j = 0; j < interval_size && (i+j) < bytes_read; j++)
- temp += abs((unsigned char) buf[i+j]-0x80);
- if (!(remain = interval_size - j)) {
- /* Wait until queue not full */
- while ((end == QUEUE_SIZE && front == 0) || end == front-1);
- /* Save average amplitude in queue */
- queue[end++] = temp / interval_size;
- end %= QUEUE_SIZE;
- }
- }
-
- if (first_enter) {
- first_enter = 0;
- /* Schedule to update DB meter every 1/10th second */
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 1000000 / 10;
- value.it_value.tv_sec = 0;
- value.it_value.tv_usec = 1000000 / 10;
-
- signal(SIGALRM, print_bar);
- setitimer(ITIMER_REAL, &value, &ovalue);
- }
-
- do {
- bytes_read = read(fd, buf, BUF_SIZE);
- if (bytes_read == -1 && errno != EINTR) {
- perror(argv[1]);
- exit(-1);
- }
- } while (bytes_read == -1 && errno == EINTR);
- if (!strcmp(argv[3], "-")) {
- write_lock = 1;
- signal(SIGCHLD, write_finished);
- /* Write to standard output */
- if (!fork()) {
- /* Child */
- if (write(1, buf, bytes_read) == -1) {
- perror("stdout write");
- exit(-1);
- }
- exit(0);
- }
- /* Wait for child to finish writing */
- while(write_lock);
- }
- } /* end while(bytes_read) */
-
- /* Wait for playing to finish */
- while (front != end);
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- value.it_value.tv_sec = 0;
- value.it_value.tv_usec = 0;
- setitimer(ITIMER_REAL, &value, &ovalue);
-
- close(fd);
- }
-
- /*
- * Update DB meter (called every 1/10th second)
- */
- void print_bar(int dummy)
- {
- int i, value;
- static prev_value = -1;
-
- if (front == end) {
- fprintf(stderr, "\nqueue empty!\n");
- exit(-1);
- }
-
- /* Take saved average amplitude from queue and update DB meter */
- value = queue[front++];
- front %= QUEUE_SIZE;
-
- if (value != prev_value) {
- prev_value = value;
- if (value < 0 || value > 128)
- fprintf(stderr, "Wrong!: %d \n", value); /* Value out of range */
-
- fprintf(stderr, "%c[1;1H", 27); /* home cursor */
- for (i = 0; i < 80; i++)
- if (i < value)
- fprintf(stderr, "%c[1m#%c[0m", 27, 27); /* print a '#' in bold */
- else
- fprintf(stderr, "#"); /* print a '#' unbolded */
- fprintf(stderr, "\n");
- }
- signal(SIGALRM, print_bar);
- }
-
- /*
- * Release write lock when child finishes writing
- */
- void write_finished(int dummy)
- {
- write_lock = 0;
- }
-